#include <stdlib.h>

/* Deux macros pratiques, utilisées dans les allocations */
#define NEW(howmany, type) (type *) calloc((unsigned) howmany, sizeof(type))
#define nil(type) (type *) 0

#define FALSE 0
#define TRUE 1

#define ERROR_FILE 1
#define ERROR_SYNTAX 2
#define ERROR_VAR 3
#define ERROR_METH 4
#define ERROR_CLASSE 5
#define ERROR_TYPE 6

/* Etiquettes pour les noeuds de l'arbre de syntaxe abstraite representant une
 * expression.
 * Les opérateurs arithmétiques sont directement utilisés aussi comme
 * etiquettes.
 */
typedef enum {
	Self,
	Super,
	Id,
	CsteInt,
	CsteSt,
	Aff,
	EQ, NEQ, GT, GE, LT, LE,	/* les differents operateurs de comparaison */
	ITE,                     	/* le if-then-else */
	NOP, 			   		 	/* etiquette "auxiliaire */
	Opp,			   		 	/* l'oppose */
	Unary,
	New,
	Bloc,
	Envoi,
	Selec,
	Cible
} etiquette;




/***** UNIONS *****/

/* Les constantes littérales du langage : instances d'Entier ou Chaîne */
typedef union {
	char *chaine;
	int entier;
} cste;


/* la structure d'un noeud de l'arbre: un noeud interne ou une feuille */
typedef union {
	char *S;			/* feuille de type Identificateur */
	struct _fct *F;		/* feuille de type Identificateur de fonction */
	cste C;	 	  		/* feuille de type constante */
	struct _arbre *A;  	/* noeud interne : un operateur et deux operandes */
	struct _classe *L;
	struct _var *V;
	struct _expr *X;
	struct _bloc *B;
	int E;
} noeud;




/***** STRUCTURES *****/

/* Liste de patrons de classe */
typedef struct _classe {
	char *nom;	/* Nom de la classe */
	struct _var *lvar;	/* Liste des variables (et constantes) */
	struct _meth *lmeth;	/* <-- casque ! (lol le jeu de mots) Liste des méthodes */
	struct _var *args; /*Arguments du constructeur*/
	struct _classe *herit; /* Peut-être pas besoin, surement juste besoin
	d'ajouter les variables et les méthodes de la classe héritée dans les
	listes. Ce sera même plus facile à traiter après. A voir !!! */
	struct _expr *params;
	int nbMeths; /*Nombre de méthodes de la classe*/
	int nbChamps; /*Nombre de champs de la classe*/
	int gp; /*Position du squelette de la classe par rapport au pointeur gp*/
	struct _classe *suiv;	/* Classe suivante (liste) */
} classe, *pclasse;


/* Une structure pour englober la classe et les paramètres d'un extends */
typedef struct {
	classe *cl;
	struct _expr *params;
} ext, *pext;


/* Liste de variables (et constantes) */
typedef struct _var {
	char *nom;	/* Nom de la variable */
	int override;
	pclasse type;	/* Valeur de la variable (incluant le type) */
	int modifiable; /* Pour différencier un val (constante non modifiable) d'un
	var (modifiable) */
	struct _expr *val;
	int fp; /*La position de la variable par rapport au pointeur fp*/
	struct _var *suiv;	/* Variable suivante (liste) */
} var, *pvar;


/* Définition d'un bloc (liste/suite d'expressions).
 * Les expressions sont des arbres syntaxiques. */
typedef struct _expr {
	struct _arbre *expre;	/* L'expresion courante */
	struct _expr *suiv;	/* L'expression suivante */
} expr, *pexpr;


/* Liste de méthodes pour les classes*/
typedef struct _meth {
	char *nom;	/* Nom de la méthode */
	int override;
	int hasParams;	// Sert à différencier f et f()
	pvar args;
	int nbArgs;
	struct _bloc *corps;	/* Corps de la méthode */
	classe *retour;
	struct _meth *suiv;	/* Méthode suivante */
} meth, *pmeth;


/* Identifiant d'une fonction avec ses paramètres d'appels */
typedef struct _fct {
	char *nom;
	pexpr params;
} fct, *pfct;


/* Un arbre (expression) */
typedef struct _arbre {
	char op;				/* une etiquette: voir l'énumeration ci-dessus */
	noeud gauche, droit;  	/* deux noeuds: internes ou feuilles */
} arbre, *parbre;


typedef struct _bloc {
	pexpr listExpr;
	pvar localContext;
} bloc, *pbloc;




typedef union {
	char C;		/* necessaire pour flex */
	pext T;
	pclasse L;	/* les autres correspondent aux variantes utilisees */
	pvar V;		/* dans les actions associees aux productions de */
	pbloc B;	/* la grammaire. */
	pexpr X;
	pmeth M;
	parbre A;
	int E;
	char *S;
} YYSTYPE;

void ecrireLigne(char* ligne);
pclasse ecrireBloc(pbloc bloc, pvar context, pvar args, pclasse classContext);
pclasse ecrireExpr(parbre exp, pvar context, pvar args, pclasse classContext);
pclasse initClasses();
pclasse GetClasseIn(char *nom, pclasse lc);

#define YYSTYPE YYSTYPE
